#include "BaseType.h"
#include "Tracer.h"
#include "ComUtil.h"
using namespace std;
using namespace libemb;

/**
 * 访问者模式：
 * 1.访问者模式的目的：将数据操作和数据结构分离。
 * 适用场景：
 * 1.对象结构比较稳定，但经常需要在此对象结构上定义新的操作。
 * 2.需要对对象进行很多不相关的操作，而且新增操作时不能修改这些对象结构类。
 **/

class Engineer;
class Manager;

//抽象访问者，可以访问不同对象结构
class Visitor{
DECL_CLASSNAME(Visitor)
public:
    virtual void visit(Engineer* engineer)=0;
    virtual void visit(Manager* manager)=0;
};

//元素基类
class Staff{
DECL_CLASSNAME(Staff)
private:
    std::string m_name;
    int m_kpi;
public:
    Staff(std::string name)
    {
        m_name = name;
        m_kpi = ComUtil::random(100);
    }
    std::string name(){return m_name;}
    int kpi(){return m_kpi;}
    //关键方法：接收访问，每个元素都可以被访问者访问
    virtual void accept(Visitor* visitor)=0;
};

//元素1：工程师
class Engineer:public Staff{
DECL_CLASSNAME(Engineer)
private:
    int m_codeLines;
public:
    Engineer(std::string name):Staff(name){
        m_codeLines = ComUtil::random(100000);
    };
    int codeLines(){return m_codeLines;}
    void accept(Visitor* visitor) override
    {
        //让访问者去访问，具体访问什么则由访问者自己去定义
        visitor->visit(this);
    }
};

//元素2：经理
class Manager:public Staff{
DECL_CLASSNAME(Manager)
private:
    int m_products;
public:
    Manager(std::string name):Staff(name){
        m_products = ComUtil::random(10);
    };
    int products(){return m_products;}
    void accept(Visitor* visitor) override
    {
        //让访问者去访问，具体访问什么则由访问者自己去定义
        visitor->visit(this);
    }
};

//CTO：特别关注工程师的代码行数
class CTOVisitor:public Visitor{
DECL_CLASSNAME(CTOVisitor)
public:
    void visit(Engineer* engineer) override
    {
        //自定义访问的操作
        TRACE_INFO_CLASS("Engineer -- name: %s, kpi: %d, code lines: %d",CSTR(engineer->name()),engineer->kpi(),engineer->codeLines());
    }
    void visit(Manager* manager) override
    {
        //自定义访问的操作
        TRACE_INFO_CLASS("Manager -- name: %s, kpi: %d",CSTR(manager->name()),manager->kpi());
    }
};

//CEO：特别关注项目经理的项目数
class CEOVisitor:public Visitor{
DECL_CLASSNAME(CEOVisitor)
public:
    void visit(Engineer* engineer) override
    {
        //自定义访问的操作
        TRACE_INFO_CLASS("Engineer -- name: %s, kpi: %d",CSTR(engineer->name()),engineer->kpi());
    }
    void visit(Manager* manager) override
    {
        //自定义访问的操作
        TRACE_INFO_CLASS("Manager -- name: %s, kpi: %d, products:%d",CSTR(manager->name()),manager->kpi(),manager->products());
    }
};

int main()
{
    Tracer::getInstance().setLevel(TRACE_LEVEL_DBG);
	Tracer::getInstance().addSink(std::make_shared<STDSink>()).start();

    Engineer engineer("Elisa");
    Manager manager("Michale");

    CTOVisitor cto;
    CEOVisitor ceo;

    //cto查看所有staff的报表
    TRACE_INFO("------CTO check KPI------");
    cto.visit(&engineer);
    cto.visit(&manager);

    //ceo查看所有staff的报表
    TRACE_INFO("------CEO check KPI------");
    ceo.visit(&engineer);
    ceo.visit(&manager);

    return RC_OK;
}